package org.activiti.web;
 
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.quickbundle.base.web.page.RmPageVo;
import org.quickbundle.project.IGlobalConstants;
import org.quickbundle.project.RmProjectHelper;
import org.quickbundle.project.common.vo.RmCommonVo;
import org.quickbundle.tools.helper.RmJspHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SimplePropertyPreFilter;
import com.dfhc.ISystemConstant;
import com.dfhc.PjException;
import com.dfhc.pub.concurrencycontrol.RequestConcurrentRoute;
import com.dfhc.pub.service.FileDownloadService;
import com.dfhc.pub.service.FileLockService;
import com.dfhc.util.CryptoHelper;
import com.dfhc.util.FileOperateHelper;
import com.dfhc.util.StringHelper;
import com.dfhc.wk.frontflowdef.service.FrontFlowDefService;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
 * 流程模型控制器
 * 
 * @author henryyan
 */
@Controller
@RequestMapping(value = "/model")
public class ModelController {
 
  protected Logger logger = LoggerFactory.getLogger(getClass());
 
  @Autowired
  RepositoryService repositoryService;
  @Autowired
  RuntimeService  runtimeService;
  @Autowired
  IdentityService identityService;
  @Autowired
  /**
   * 文件加锁服务
   */	
  private FileLockService fileLockService;  
  @Autowired
  /**
   * 文件加锁服务
   */	
  private FrontFlowDefService frontFlowDefService;
  @Autowired
  /**
   * 文件下载服务
   */
  private FileDownloadService fileDownloadService;  
  
  /**
   * 模型列表
   */
  @RequestMapping(value = "listmodel")
  public ModelAndView modelList(HttpServletRequest request) {
    ModelAndView mav = new ModelAndView("/activiti/explorer/model-list");
//    RmPageVo pageVo = RmJspHelper.transctPageVo(request, (int) repositoryService.createModelQuery().count());
//    
//    List<Model> list = repositoryService.createModelQuery().orderByCreateTime().desc().listPage(pageVo.getStartIndex()-1, pageVo.getPageSize());
//
//
//    mav.addObject("list", list);
    return mav;
  }
  /**
   * ajax 请求模型列表数据
   * @param model
   * @param request
   * @return
   * @throws IOException 
   */
  @RequestMapping(value = "ajaxList")
  public void ajaxList(HttpServletRequest request, HttpServletResponse response) throws IOException{
  	boolean bLock = false;
  	try{
	    	bLock = RequestConcurrentRoute.getSingleton().lock(request.getParameter(ISystemConstant.JSGUID));    

	        Map<String,Object> dataMap=new HashMap<String,Object>();
            String name = request.getParameter("name");
	        String page=request.getParameter("page")==null?"1":request.getParameter("page");
	        String rows=request.getParameter("rows")==null?ISystemConstant.DEFAULT_PAGE_SIZE:request.getParameter("rows");
	        int rowsInt=Integer.parseInt(rows);//页大小
	        int pageInt=Integer.parseInt(page);//当前页
	    
	        RmPageVo pageVo = null;
	        //如果查询名称条件为空
	        if(StringHelper.isEmpty(name)){
	        	pageVo  = RmJspHelper.transctPageVo(request, (int) repositoryService.createModelQuery().count());
	        }else{
	        	pageVo  = RmJspHelper.transctPageVo(request, (int) repositoryService.createModelQuery().modelNameLike("%"+name+"%").count());
	        }
	        pageVo.setPageSize(rowsInt);
	        pageVo.setCurrentPage(pageInt);
	        String orderStr = RmJspHelper.getOrderStr(request);  //得到排序信息
	        if(StringHelper.isEmpty(orderStr)){
	            String sidx=request.getParameter("sidx")==null?"id":request.getParameter("sidx");
          	    String sord=request.getParameter("sord")==null?"desc":request.getParameter("sord");
          	    orderStr=sidx+" "+sord;
	        }
	        List<Model> list = null;
	        if(StringHelper.isEmpty(name)){
	        	list = repositoryService.createModelQuery().orderByCreateTime().desc().listPage(pageVo.getStartIndex()-1, pageVo.getPageSize());      
	        }else{
	        	list = repositoryService.createModelQuery().modelNameLike("%"+name+"%").orderByCreateTime().desc().listPage(pageVo.getStartIndex()-1, pageVo.getPageSize());
	        }
       
	        dataMap.put("page",  pageVo.getCurrentPage());
	        dataMap.put("total",  pageVo.getPageCount());
	        dataMap.put("records",  pageVo.getRecordCount());
	        dataMap.put("rows", list);
       
	        response.setCharacterEncoding("UTF-8"); 
	        response.getWriter().write(JSONObject.toJSONString(dataMap));
        }finally{
	        //最后解锁
	        RequestConcurrentRoute.getSingleton().unLock(request.getParameter(ISystemConstant.JSGUID), bLock);
        }
  }  
  /**
   * 创建模型
   */
  @RequestMapping(value = "create", 
			consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
  @ResponseBody
  public Map<String,Object> create(@RequestParam("name") String name, @RequestParam("key") String key, @RequestParam("description") String description,
          HttpServletRequest request, HttpServletResponse response) {
  	boolean bLock = false;
  	try{
	      bLock = RequestConcurrentRoute.getSingleton().lock(request.getParameter(ISystemConstant.JSGUID));    
	      ObjectMapper objectMapper = new ObjectMapper();
	      ObjectNode editorNode = objectMapper.createObjectNode();
	      editorNode.put("id", "canvas");
	      editorNode.put("resourceId", "canvas");
	      ObjectNode stencilSetNode = objectMapper.createObjectNode();
	      stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
	      editorNode.put("stencilset", stencilSetNode);
	      Model modelData = repositoryService.newModel();
	 
	      ObjectNode modelObjectNode = objectMapper.createObjectNode();
	      modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, name);
	      modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
	      description = StringUtils.defaultString(description);
	      modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
	      modelData.setMetaInfo(modelObjectNode.toString());
	      modelData.setName(name);
	      modelData.setKey(StringUtils.defaultString(key));
	 
	      repositoryService.saveModel(modelData);
	      repositoryService.addModelEditorSource(modelData.getId(), editorNode.toString().getBytes("utf-8"));
	 
	      //response.sendRedirect(request.getContextPath() + "/modeler.html?modelId=" + modelData.getId());
	      Map<String,Object> result = new HashMap<String,Object>();
	      result.put(ISystemConstant.AJAX_STATUS, ISystemConstant.AJAX_RESULT_SUCCESS);
	      result.put(ISystemConstant.AJAX_MESSAGE, "创建模型成功!");
	      result.put("modelId",modelData.getId());
	      return result;
	    } catch (Exception e) {
	      logger.error("创建模型失败：", e);
	      Map<String,Object> result = new HashMap<String,Object>();
	      result.put(ISystemConstant.AJAX_STATUS, ISystemConstant.AJAX_RESULT_FAIL);
	      result.put(ISystemConstant.AJAX_MESSAGE, "创建模型失败!");
	      return result;
	    }finally{
	        //最后解锁
	        RequestConcurrentRoute.getSingleton().unLock(request.getParameter(ISystemConstant.JSGUID), bLock);
        }
  }
 
  /**
   * 根据Model部署流程
   */
  @RequestMapping(value = "deploy", 
			consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
  @ResponseBody
  public Map<String,Object> deploy( HttpServletRequest request) {
	  	String modelId=null;
	  	boolean bLock = false;
	  	try{
    	  bLock = RequestConcurrentRoute.getSingleton().lock(request.getParameter(ISystemConstant.JSGUID));    
	      String ids[] = request.getParameterValues(IGlobalConstants.REQUEST_IDS);
	      modelId = ids[0];
	      Model modelData = repositoryService.getModel(ids[0]);
	      ObjectNode modelNode = (ObjectNode) new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId()));
	      byte[] bpmnBytes = null;
	 
	      BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
	     // bpmnBytes = new BpmnXMLConverter().convertToXML(model);
	      bpmnBytes =new BpmnXMLConverter().convertToXML(model,"GBK");
	 
	      String processName = modelData.getName() + ".bpmn20.xml";
	      Deployment deployment = repositoryService.createDeployment().name(modelData.getName()).addString(processName, new String(bpmnBytes)).deploy();
	      Map<String,Object> result = new HashMap<String,Object>();
	      result.put(ISystemConstant.AJAX_STATUS, ISystemConstant.AJAX_RESULT_SUCCESS);
	      result.put(ISystemConstant.AJAX_MESSAGE, "部署成功，部署ID=" + deployment.getId());
	      return result;
	    } catch (Exception e) {
	      logger.error("根据模型部署流程失败：modelId={}", modelId, e);
	      Map<String,Object> result = new HashMap<String,Object>();
	      result.put(ISystemConstant.AJAX_STATUS, ISystemConstant.AJAX_RESULT_FAIL);
	      result.put(ISystemConstant.AJAX_MESSAGE, "部署失败");
	      return result;
	    }finally{
	      //最后解锁
	      RequestConcurrentRoute.getSingleton().unLock(request.getParameter(ISystemConstant.JSGUID), bLock);
	    }
	 	
  }
 
  /**
   * 导出model的xml文件
   */
  @RequestMapping(value = "export")  
  public void export(HttpServletResponse response,HttpServletRequest request,RedirectAttributes redirectAttributes) {
	  	boolean bLock = false;
	  	String modelId ="";
	  	try{
	  	  modelId = request.getParameter("modelId");
      	  bLock = RequestConcurrentRoute.getSingleton().lock(request.getParameter(ISystemConstant.JSGUID));    
  
	      Model modelData = repositoryService.getModel(modelId);
	      BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
	      JsonNode editorNode = new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId()));
	      BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode);
	      BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
	      byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel);
	 
//	      ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes);
//	      IOUtils.copy(in, response.getOutputStream());
//	      String filename = bpmnModel.getMainProcess().getId() + ".bpmn20.xml";
//	      response.setHeader("Content-Disposition", "attachment; filename=" + filename);
//	      response.flushBuffer();
	      String filename = bpmnModel.getMainProcess().getId() + ".bpmn20.xml";
	      fileDownloadService.downloadStream(filename, bpmnBytes, response);	      
     } catch (Exception e) {
      logger.error("导出model的xml文件失败：modelId={}", modelId, e);
      Map<String,Object> result = new HashMap<String,Object>();
      result.put(ISystemConstant.AJAX_STATUS, ISystemConstant.AJAX_RESULT_FAIL);
      result.put(ISystemConstant.AJAX_MESSAGE, "导出model的xml文件失败!");
      response.setCharacterEncoding("UTF-8"); 
      try {
		response.getWriter().write(JSONObject.toJSONString(result));
	  } catch (IOException e1) {			
			e1.printStackTrace();
	  }
     }finally{
        //最后解锁
        RequestConcurrentRoute.getSingleton().unLock(request.getParameter(ISystemConstant.JSGUID), bLock);
     }
  }
  @RequestMapping(value = "delete", 
			consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
  @ResponseBody
  public Map<String,Object> delete(HttpServletRequest request) {
  	boolean bLock = false;
  	try{
	   	  bLock = RequestConcurrentRoute.getSingleton().lock(request.getParameter(ISystemConstant.JSGUID));  
	      String[] ids = RmJspHelper.getArrayFromRequest(request, IGlobalConstants.REQUEST_IDS); //从request获取多条记录id
	      repositoryService.deleteModel(ids[0]);
	      Map<String,Object> result = new HashMap<String,Object>();
	      result.put(ISystemConstant.AJAX_STATUS, ISystemConstant.AJAX_RESULT_SUCCESS);
	      result.put(ISystemConstant.AJAX_MESSAGE, "删除成功!");
	      return result;
      }finally{
	      //最后解锁
	      RequestConcurrentRoute.getSingleton().unLock(request.getParameter(ISystemConstant.JSGUID), bLock);
      }      
  }
  /**
   * 列出所有流程实例
   */
  @RequestMapping(value = "listinstance")
  public String listinstance(HttpServletRequest request) {
	  RmPageVo pageVo = RmJspHelper.transctPageVo(request, (int) runtimeService.createProcessInstanceQuery().count());
	  List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().orderByProcessInstanceId().desc().listPage(pageVo.getStartIndex()-1, pageVo.getPageSize());
	  request.setAttribute("beans", list);
	  String ctx = request.getContextPath(); 
	  request.setAttribute("ctx", ctx);
	  //return "/activiti/explorer/running-manage";
	  return "/activiti/wk/listInstance";
  }
  /**
   * 列出所有流程实例(业务申请)
   */
  @RequestMapping(value = "businessApplication")
  public String businessApplication(HttpServletRequest request) {
//	  org.activiti.web.Page<ProcessDefinition> page = new org.activiti.web.Page<ProcessDefinition>(PageUtil.PAGE_SIZE);
//	  int[] pageParams = PageUtil.init(page, request);
//	  List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().listPage(pageParams[0], pageParams[1]);
//	  page.setResult(list);
//	  page.setTotalCount(runtimeService.createProcessInstanceQuery().count());
//	  request.setAttribute("page", page);
//	  return "/activiti/explorer/business-application";
	  RmPageVo pageVo = RmJspHelper.transctPageVo(request, (int) repositoryService.createProcessDefinitionQuery().count());
	  List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().orderByProcessDefinitionId().desc().listPage(pageVo.getStartIndex()-1, pageVo.getPageSize());
	  request.setAttribute("beans", list);
	  String ctx = request.getContextPath(); 
	  request.setAttribute("ctx", ctx);
	  //return "/activiti/explorer/running-manage";
	  return "/activiti/wk/listBusinessApplication";
  }
  /**
   * 启动流程实例  
   * @param processDefinitionId
   * @param request
   * @return
   */
  @RequestMapping(value = "start", 
			consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
  @ResponseBody
  public Map<String,Object> start(ServletRequest request,HttpServletResponse response) {
	 
	  Map<String,Object> result = new HashMap<String,Object>();
	  
	  	boolean bLock = false;
	  	try{
     	  bLock = RequestConcurrentRoute.getSingleton().lock(request.getParameter(ISystemConstant.JSGUID));    

		  String processDefinitionId = request.getParameter("processDefinitionId");
		  identityService.setAuthenticatedUserId(RmProjectHelper.getRmUserId(request));
	      runtimeService.startProcessInstanceById(processDefinitionId);
     
      } catch (Exception e) {
    	  logger.error("error on deploy process, because of file input stream");
         
          result.put(ISystemConstant.AJAX_STATUS, ISystemConstant.AJAX_RESULT_FAIL);
          result.put(ISystemConstant.AJAX_MESSAGE, e.getMessage());
          return result;
      }finally{
	      //最后解锁
	      RequestConcurrentRoute.getSingleton().unLock(request.getParameter(ISystemConstant.JSGUID), bLock);
      }
      
      result.put(ISystemConstant.AJAX_STATUS, ISystemConstant.AJAX_RESULT_SUCCESS);
      result.put(ISystemConstant.AJAX_MESSAGE, "启动成功");
      return result;
//	      return "redirect:/model/listprocedef";
  }
  /**
   * 流程列表
   */
  @RequestMapping(value = "listprocedef")
  public String procedefList(HttpServletRequest request) {    
    return "/activiti/explorer/process-list";   
  }
  /**
   * ajax 请求流程定义列表数据
   * @param model
   * @param request
   * @return
   * @throws IOException 
   */
  @RequestMapping(value = "ajaxListprocedef")
  public void ajaxListprocedef(HttpServletRequest request, HttpServletResponse response) throws IOException{
  	boolean bLock = false;
  	try{
	    	bLock = RequestConcurrentRoute.getSingleton().lock(request.getParameter(ISystemConstant.JSGUID));    

	        Map<String,Object> dataMap=new HashMap<String,Object>();
            String name = request.getParameter("name");
	        String page=request.getParameter("page")==null?"1":request.getParameter("page");
	        String rows=request.getParameter("rows")==null?ISystemConstant.DEFAULT_PAGE_SIZE:request.getParameter("rows");
	        int rowsInt=Integer.parseInt(rows);//页大小
	        int pageInt=Integer.parseInt(page);//当前页
	    
	        RmPageVo pageVo = null;
	        //如果查询名称条件为空
	        if(StringHelper.isEmpty(name)){
	        	pageVo  = RmJspHelper.transctPageVo(request, (int)  repositoryService.createProcessDefinitionQuery().count());
	        }else{
	        	pageVo  = RmJspHelper.transctPageVo(request, (int) repositoryService.createProcessDefinitionQuery().processDefinitionNameLike("%"+name+"%").count());
	        }
	        pageVo.setPageSize(rowsInt);
	        pageVo.setCurrentPage(pageInt);
	        String orderStr = RmJspHelper.getOrderStr(request);  //得到排序信息
	        if(StringHelper.isEmpty(orderStr)){
	            String sidx=request.getParameter("sidx")==null?"id":request.getParameter("sidx");
          	    String sord=request.getParameter("sord")==null?"desc":request.getParameter("sord");
          	    orderStr=sidx+" "+sord;
	        }
	        List<ProcessDefinition> list = null;
	        
	        
	        if(StringHelper.isEmpty(name)){
	        	list = repositoryService.createProcessDefinitionQuery().orderByDeploymentId().desc().listPage(pageVo.getStartIndex()-1, pageVo.getPageSize());      
	        }else{
	        	list = repositoryService.createProcessDefinitionQuery().processDefinitionNameLike("%"+name+"%").orderByDeploymentId().desc().listPage(pageVo.getStartIndex()-1, pageVo.getPageSize());
	        }
	        
	        dataMap.put("page",  pageVo.getCurrentPage());
	        dataMap.put("total",  pageVo.getPageCount());
	        dataMap.put("records",  pageVo.getRecordCount());
	        dataMap.put("rows", list);
       
	        response.setCharacterEncoding("UTF-8");
	        //指定需要转换为json的属性列表
	        SimplePropertyPreFilter filter = new SimplePropertyPreFilter(ProcessDefinition.class, "id","deploymentId","name","key","version","resourceName","diagramResourceName","suspended");  

	        response.getWriter().write(JSONObject.toJSONString(dataMap,filter));
        }finally{
	        //最后解锁
	        RequestConcurrentRoute.getSingleton().unLock(request.getParameter(ISystemConstant.JSGUID), bLock);
        }
  }  

  /**
   * 文件方式部署流程资源
   */
  @RequestMapping(value = "/filedeploy")
  public void deploy(HttpServletRequest request,HttpServletResponse response) {
	  	boolean bLock = false;
	  	try{
	      bLock = RequestConcurrentRoute.getSingleton().lock(request.getParameter(ISystemConstant.JSGUID));    

    	  List<MultipartFile> files = FileOperateHelper.listMultipartFile(request);
    	  if(CollectionUtils.isEmpty(files)){
    		  throw new PjException("缺少文件!");
    	  }
    	  MultipartFile file = files.get(0);
    	  // 获取上传的文件名
    	  String fileName = file.getOriginalFilename();
          // 得到输入流（字节流）对象
          InputStream fileInputStream = file.getInputStream();

          // 文件的扩展名
          String extension = FileOperateHelper.getFileSuffix(fileName);

          // zip或者bar类型的文件用ZipInputStream方式部署
          DeploymentBuilder deployment = repositoryService.createDeployment();
          if (extension.equalsIgnoreCase(".zip") || extension.equalsIgnoreCase(".bar")) {
              ZipInputStream zip = new ZipInputStream(fileInputStream);
              deployment.addZipInputStream(zip);
          } else {
              // 其他类型的文件直接部署
              deployment.addInputStream(fileName, fileInputStream);
          }
          Deployment deployment1 = deployment.deploy();
          
          ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployment1.getId()).singleResult();
          InputStream bpmnStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(),
                  processDefinition.getResourceName());
          XMLInputFactory xif = XMLInputFactory.newInstance();
          InputStreamReader in = new InputStreamReader(bpmnStream, "UTF-8");
          XMLStreamReader xtr = xif.createXMLStreamReader(in);
          BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr);

          BpmnJsonConverter converter = new BpmnJsonConverter();
          ObjectNode modelNode = converter.convertToJson(bpmnModel);
          Model modelData = repositoryService.newModel();
          modelData.setKey(processDefinition.getKey());
          modelData.setName(processDefinition.getResourceName());
          modelData.setCategory(processDefinition.getDeploymentId());

          ObjectNode modelObjectNode = new ObjectMapper().createObjectNode();
          modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, processDefinition.getName());
          modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
          modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, processDefinition.getDescription());
          modelData.setMetaInfo(modelObjectNode.toString());

          repositoryService.saveModel(modelData);

          repositoryService.addModelEditorSource(modelData.getId(), modelNode.toString().getBytes("utf-8"));
          Map<String, Object> result = new HashMap<String, Object>();//
	  	  result.put(ISystemConstant.AJAX_STATUS, ISystemConstant.AJAX_RESULT_SUCCESS);		
	  	  result.put(ISystemConstant.AJAX_MESSAGE, "导入成功!");
	  	  response.setContentType("text/html;charset=utf-8");
	  	  try {
	  			response.getWriter().print(JSONObject.toJSONString(result));
	  			response.getWriter().flush();
	  	  } catch (Exception ex) {
	  			ex.printStackTrace();
	  	  }          
      } catch (Exception e) {
  	    logger.error("error on deploy process, because of file input stream");
		Map<String, Object> result = new HashMap<String, Object>();//
		result.put(ISystemConstant.AJAX_STATUS, ISystemConstant.AJAX_RESULT_FAIL);		
		result.put(ISystemConstant.AJAX_MESSAGE, e.getMessage());
		response.setContentType("text/html;charset=utf-8");
		try {
			response.getWriter().print(JSONObject.toJSONString(result));
			response.getWriter().flush();
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return;
      }finally{
	    //最后解锁
	    RequestConcurrentRoute.getSingleton().unLock(request.getParameter(ISystemConstant.JSGUID), bLock);
      }

  }  
  
  
  /**
   * 转换流程定义为模型
   * @param processDefinitionId
   * @return
   * @throws UnsupportedEncodingException
   * @throws XMLStreamException
   */
  @RequestMapping(value = "/convert-to-model", 
			consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
  @ResponseBody
  public Map<String,Object> convertToModel(HttpServletRequest request)
          throws UnsupportedEncodingException, XMLStreamException {
	  Map<String, Object> result = new HashMap<String, Object>();
	  
  	boolean bLock = false;
  	try{
      	  bLock = RequestConcurrentRoute.getSingleton().lock(request.getParameter(ISystemConstant.JSGUID));  		
		  String processDefinitionId = request.getParameter("processDefinitionId");
		  ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
		          .processDefinitionId(processDefinitionId).singleResult();
		  InputStream bpmnStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(),
		          processDefinition.getResourceName());
		  XMLInputFactory xif = XMLInputFactory.newInstance();
		  InputStreamReader in = new InputStreamReader(bpmnStream, "UTF-8");
		  XMLStreamReader xtr = xif.createXMLStreamReader(in);
		  BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr);
		
		  BpmnJsonConverter converter = new BpmnJsonConverter();
		  ObjectNode modelNode = converter.convertToJson(bpmnModel);
		  Model modelData = repositoryService.newModel();
		  modelData.setKey(processDefinition.getKey());
		  modelData.setName(processDefinition.getResourceName());
		  modelData.setCategory(processDefinition.getDeploymentId());
		
		  ObjectNode modelObjectNode = new ObjectMapper().createObjectNode();
		  modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, processDefinition.getName());
		  modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
		  modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, processDefinition.getDescription());
		  modelData.setMetaInfo(modelObjectNode.toString());
		
		  repositoryService.saveModel(modelData);
		
		  repositoryService.addModelEditorSource(modelData.getId(), modelNode.toString().getBytes("utf-8"));
		} catch (Exception e) {
		    logger.error("error on deploy process, because of file input stream");
	  		result.put(ISystemConstant.AJAX_STATUS, ISystemConstant.AJAX_RESULT_FAIL);		
	  		result.put(ISystemConstant.AJAX_MESSAGE, e.getMessage());
	  		return result;
        }finally{
        	//最后解锁
        	RequestConcurrentRoute.getSingleton().unLock(request.getParameter(ISystemConstant.JSGUID), bLock);
        }
      
      	result.put(ISystemConstant.AJAX_STATUS, ISystemConstant.AJAX_RESULT_SUCCESS);		
		result.put(ISystemConstant.AJAX_MESSAGE, "操作成功");
		
		return result;
//      return "redirect:/chapter20/model/list";
  }

  /**
   * 读取流程资源
   *
   * @param processDefinitionId 流程定义ID
   * @param resourceName        资源名称
   */
  @RequestMapping(value = "/read-resource")
  public void readResource(@RequestParam("pdid") String processDefinitionId, @RequestParam("resourceName") String resourceName, HttpServletResponse response,HttpServletRequest request)
          throws Exception {
	  String temp = request.getParameter("resourceName");
      ProcessDefinitionQuery pdq = repositoryService.createProcessDefinitionQuery();
      ProcessDefinition pd = pdq.processDefinitionId(processDefinitionId).singleResult();
      if(StringHelper.isEmpty(temp)){
    	  temp = pd.getDiagramResourceName();
      }

      // 通过接口读取
      InputStream resourceAsStream = repositoryService.getResourceAsStream(pd.getDeploymentId(), temp);

      // 输出资源内容到相应对象
      byte[] b = new byte[1024];
      int len = -1;
      while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {
          response.getOutputStream().write(b, 0, len);
      }
  }
  /**
   * 删除已部署的流程
   * @param deploymentId  部署id
   * @return
   */
  @RequestMapping(value = "deleteDeployment", 
			consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
  @ResponseBody
  public Map<String,Object> deleteDeployment( HttpServletRequest request) {
	 
  	boolean bLock = false;
  	String deploymentId=request.getParameter("deploymentId");
  	try{
    	bLock = RequestConcurrentRoute.getSingleton().lock(request.getParameter(ISystemConstant.JSGUID));    

		  Map<String,Object> result = new HashMap<String,Object>();
		  
	      repositoryService.deleteDeployment(deploymentId,true);      
	      
	      result.put(ISystemConstant.AJAX_STATUS, ISystemConstant.AJAX_RESULT_SUCCESS);
	      result.put(ISystemConstant.AJAX_MESSAGE, "操作成功!");
	      return result;
	      
	  } catch (Exception e) {
	  	    logger.error("error on deploy process, because of file input stream");
			Map<String, Object> result = new HashMap<String, Object>();//
			result.put(ISystemConstant.AJAX_STATUS, ISystemConstant.AJAX_RESULT_FAIL);		
			result.put(ISystemConstant.AJAX_MESSAGE, e.getMessage());
			return result;
	      }finally{
		    //最后解锁
		    RequestConcurrentRoute.getSingleton().unLock(request.getParameter(ISystemConstant.JSGUID), bLock);
	      }

//      return "redirect:/model/listprocedef";
  }
  /**
   * 挂起流程实例
   * @param processInstanceId  实例id
   * @return
 * @throws Exception 
   */
  @RequestMapping(value = "update/suspend")
  public String suspendProcessInstanceById(HttpServletRequest request) throws Exception {
	  String processInstanceId = request.getParameter("pid");
      runtimeService.suspendProcessInstanceById(processInstanceId);      
      return "redirect:"+CryptoHelper.encryptUrl(request,"/model/listinstance");
  }
  /**
   * 激活或挂起流程定义
   * @param processDefinitionId  流程定义id
   * @return
   */
  @RequestMapping(value = "/activeorsuspendProcessDefinition", 
			consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
  @ResponseBody
  public Map<String,Object> activeorsuspendByProcessDefinitionId(HttpServletRequest request) {
	  Map<String,Object> result = new HashMap<String,Object>();
	  String processDefinitionId = request.getParameter("processDefinitionId");
      ProcessDefinition processDef = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
      if(processDef==null){
    	  result.put(ISystemConstant.AJAX_STATUS, ISystemConstant.AJAX_RESULT_FAIL);
          result.put(ISystemConstant.AJAX_MESSAGE, "流程定义:"+processDefinitionId+"没找到!");
          return result;
      }
      if(processDef.isSuspended()){
    	  repositoryService.activateProcessDefinitionById(processDefinitionId);    	  
      }else{
    	  repositoryService.suspendProcessDefinitionById(processDefinitionId);
      }
      result.put(ISystemConstant.AJAX_STATUS, ISystemConstant.AJAX_RESULT_SUCCESS);
      result.put(ISystemConstant.AJAX_MESSAGE, "操作成功!");
      return result;
      //return "redirect:/model/listinstance";
  }


  
  /**
   * 前台设计流程
   */
  @RequestMapping(value = "design")
  public ModelAndView design() {
    ModelAndView mav = new ModelAndView("/activiti/design/design");
    
    return mav;
  }
  
  /**
   * 前台设计流程
   */
  @RequestMapping(value = "frontDesign")
  public ModelAndView frontDesign(HttpServletRequest request) {
	 
	String procDefId = request.getParameter("procDefId");
	request.setAttribute("procDefId", procDefId);
    ModelAndView mav = new ModelAndView("/activiti/design/frontDesign");
    
    return mav;
  }
  
  /**
   * 前台流程列表
   */
  @RequestMapping(value = "listFrontProcedef")
  public String listFrontProcedef(HttpServletRequest request) {    
    return "/activiti/explorer/front-process-list";   
  }
  /**
   * ajax 请求流程定义列表数据
   * @param model
   * @param request
   * @return
   * @throws IOException 
   */
  @RequestMapping(value = "ajaxListFrontProcedef")
  public void ajaxListFrontProcedef(HttpServletRequest request, HttpServletResponse response) throws IOException{
  	boolean bLock = false;
  	try{
	    	bLock = RequestConcurrentRoute.getSingleton().lock(request.getParameter(ISystemConstant.JSGUID));    

	        Map<String,Object> dataMap=new HashMap<String,Object>();
            String name = request.getParameter("name");
//            String version = request.getParameter("version");
	        String page=request.getParameter("page")==null?"1":request.getParameter("page");
	        String rows=request.getParameter("rows")==null?ISystemConstant.DEFAULT_PAGE_SIZE:request.getParameter("rows");
	        int rowsInt=Integer.parseInt(rows);//页大小
	        int pageInt=Integer.parseInt(page);//当前页
	    
	        StringBuffer sql = new StringBuffer();
	        StringBuffer countSql = new StringBuffer();
	        sql.append("SELECT ACT_RE_PROCDEF.ID_ as id, ACT_RE_PROCDEF.NAME_ as name,ACT_RE_PROCDEF.VERSION_ as version,WK_FRONT_FLOW_DEF.CREATE_TIME as createTime,WK_FRONT_FLOW_DEF.MODIFY_TIME as modifyTime FROM ACT_RE_PROCDEF,WK_FRONT_FLOW_DEF WHERE ACT_RE_PROCDEF.ID_ = WK_FRONT_FLOW_DEF.PROC_DEF_ID ");
	        countSql.append("SELECT count(*) FROM ACT_RE_PROCDEF,WK_FRONT_FLOW_DEF WHERE ACT_RE_PROCDEF.ID_ = WK_FRONT_FLOW_DEF.PROC_DEF_ID ");
	        if(!StringHelper.isEmpty(name)){
	        	sql.append(" AND ACT_RE_PROCDEF.NAME_ like '%"+name+"%'");
	        	countSql.append(" AND ACT_RE_PROCDEF.NAME_ like '%"+name+"%'");
	        }
	        
	        sql.append(" order by modifyTime desc");
	        
	        int count = RmProjectHelper.getCommonServiceInstance().doQueryForInt(countSql.toString());
	        
	        int pageConut = 0;
	        if(count%rowsInt == 0){
	        	pageConut = count/rowsInt;
	        }else{
	        	pageConut = count/rowsInt+1;
	        }
	        
	        List<RmCommonVo> list = RmProjectHelper.getCommonServiceInstance().doQuery(sql.toString(), (pageInt-1)*rowsInt+1, pageInt*rowsInt);
	        
	        dataMap.put("page",  pageInt);
	        dataMap.put("total",  pageConut);
	        dataMap.put("records",  count);
	        dataMap.put("rows", list);
       
	        response.setCharacterEncoding("UTF-8");
	        //指定需要转换为json的属性列表
	        SimplePropertyPreFilter filter = new SimplePropertyPreFilter(ProcessDefinition.class, "id","deploymentId","name","key","version","resourceName","diagramResourceName","suspended");  

	        response.getWriter().write(JSONObject.toJSONString(dataMap,filter));
        }finally{
	        //最后解锁
	        RequestConcurrentRoute.getSingleton().unLock(request.getParameter(ISystemConstant.JSGUID), bLock);
        }
  }  
  
  /**
   * 流程监控
   * */
  @RequestMapping(value = "defMonitor")
  public String defMonitor( HttpServletRequest request, HttpServletResponse response) {
    
	  request.setAttribute("pdid", request.getParameter("pdid"));
	  request.setAttribute("pid", request.getParameter("pid"));
	  String ctx = request.getContextPath(); 
	  request.setAttribute("ctx", ctx);
	  return "/activiti/wk/defMonitor";
  }
  /**
   * 激活流程实例
   * @param processInstanceId  实例id
   * @return
 * @throws Exception 
   */
  @RequestMapping(value = "update/active")
  public String activeProcessInstanceById(HttpServletRequest request) throws Exception {
	  String processInstanceId = request.getParameter("pid");
      runtimeService.activateProcessInstanceById(processInstanceId);      
      return "redirect:"+CryptoHelper.encryptUrl(request,"/model/listinstance");
  }
}